package com.ysz.aop;

import com.ysz.annotation.Mark;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;

/**
 * @ClassName AutoAddConfig
 * @Description TODO
 * @Data 17:12
 * @Version 1.0
 * @Author ysz
 */
@Component
public class AutoAddConfig implements MethodInterceptor {
    private static final String CREATE_BY = "createBy";
    private static final String CREATE_TIME = "createTime";
    private static final String UPDATE_BY = "updateBy";
    private static final String UPDATE_TIME = "updateTime";
    private static final String INDEX = "index";

    @Autowired
    private UserInfo userInfo;

    public String getUserName() {
        return userInfo.getUserName();
    }


    /**
     * 拿到mark注解上的信息
     *
     * @param method 所调用的那个方法签名
     * @return
     * @author ysz
     * @date 2021/7/22 9:29
     */
    private HashMap<String, Object> getMarkMapping(Method method) throws NoSuchMethodException {
        //拿到目标方法上的mark注解信息
        Mark annotation = method.getAnnotation(Mark.class);
        if (annotation == null) {
            throw new RuntimeException("请检查Mark注解和execution表达式是否匹配");
        }
        HashMap<String, Object> resultMap = new HashMap<>(6);
        resultMap.put(CREATE_BY, annotation.createByMapping());
        resultMap.put(CREATE_TIME, annotation.createTimeMapping());
        resultMap.put(UPDATE_BY, annotation.updateByMapping());
        resultMap.put(UPDATE_TIME, annotation.updateTimeMapping());
        resultMap.put(INDEX, annotation.index());
        return resultMap;
    }

    /**
     * 给实体类设置4个值
     *
     * @param objects     目标方法的参数列表
     * @param markMapping mark注解上的参数信息
     * @return
     * @throws
     * @author ysz
     * @date 2021/7/22 20:41
     */
    private void methodTransfer(Object[] objects, HashMap<String, Object> markMapping) throws Throwable {
        if (objects != null && objects.length > 0) {
            Object arg = objects[(int) markMapping.get(INDEX)];
            String userName = getUserName();
            String createBy = (String) markMapping.get(CREATE_BY);
            String createTime = (String) markMapping.get(CREATE_TIME);
            String updateBy = (String) markMapping.get(UPDATE_BY);
            String updateTime = (String) markMapping.get(UPDATE_TIME);
            if (userName != null) {
                if (!"".equals(createBy) && StringUtils.isBlank(BeanUtils.getProperty(arg, createBy))) {
                    BeanUtils.setProperty(arg, createBy, userName);
                }
                if (!"".equals(createTime) && StringUtils.isBlank(BeanUtils.getProperty(arg, createTime))) {
                    BeanUtils.setProperty(arg, createTime, new Date());
                }
                if (!"".equals(updateBy) && StringUtils.isBlank(BeanUtils.getProperty(arg, updateBy))) {
                    BeanUtils.setProperty(arg, updateBy, userName);
                }
                if (!"".equals(updateTime) && StringUtils.isBlank(BeanUtils.getProperty(arg, updateTime))) {
                    BeanUtils.setProperty(arg, updateTime, new Date());
                }
            }
        }
    }

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        //拿到方法签名
        Method method = methodInvocation.getMethod();
        HashMap<String, Object> markMapping = getMarkMapping(method);
        //拿到方法参数
        Object[] arguments = methodInvocation.getArguments();
        methodTransfer(arguments, markMapping);
        //调用目标方法
        return methodInvocation.proceed();
    }
}
